﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace PloobsEngine.SceneControl
{    

    public class SSAOPostEffect : IPostEffect
    {

        Effect effect = null;
        Effect ssaofinal = null;
        EngineStuff engine;        
        Texture2D RandomTexture;
        RenderTarget2D target;
        RenderTarget2D target2;
        GaussianBlurPostEffect gbp;
        BlurMode blurMode = BlurMode.SINGLE;

        public BlurMode BlurMode
        {
            get { return blurMode; }
            set { blurMode = value; }
        }
        bool outputONLYSSAOMAP = false;

        public bool OutputONLYSSAOMAP
        {
            get { return outputONLYSSAOMAP; }
            set { outputONLYSSAOMAP = value; }
        }
        //Vector3[] rd;
        //Texture2D t;

        float jitter = 0.0013f;

        public float Jitter
        {
            get { return jitter; }
            set { jitter = value; }
        }
        float intensity = 1;

        public float Intensity
        {
            get { return intensity; }
            set { intensity = value; }
        }
        float diffscale = 1;

        public float Diffscale
        {
            get { return diffscale; }
            set { diffscale = value; }
        }

        float whiteCorrection = 0;

        public float WhiteCorrection
        {
            get { return whiteCorrection; }
            set { whiteCorrection = value; }
        }

        bool enableControl = false;

        public bool EnableControl
        {
            get { return enableControl; }
            set { enableControl = value; }
        }
        

        public void Draw(IRenderHelper rHelper, Microsoft.Xna.Framework.GameTime gt, Microsoft.Xna.Framework.Rectangle screenRec, IWorld world)
        {
            if (EnableControl)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.I))
                {
                    whiteCorrection += 0.05f;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.U))
                {
                    whiteCorrection -= 0.05f;
                }


                if (Keyboard.GetState().IsKeyDown(Keys.P))
                {
                    jitter += 0.0001f;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.O))
                {
                    jitter -= 0.0001f;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.L))
                {
                    intensity += 0.5f;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.K))
                {
                    intensity -= 0.5f;
                }

                if (Keyboard.GetState().IsKeyDown(Keys.M))
                {
                    diffscale += 0.5f;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.N))
                {
                    diffscale -= 0.5f;
                }
            }

            
             effect.Parameters["Params"].SetValue(new Vector4(EngineStuff.BackBufferWidth, EngineStuff.BackBufferHeight, world.ActiveCamera.FarPlane, intensity));
             effect.Parameters["DepthBuffer"].SetValue(rHelper[PrincipalConstants.dephRT]);
             effect.Parameters["NormalBuffer"].SetValue(rHelper[PrincipalConstants.normalRt]);
             effect.Parameters["RandomTexture"].SetValue(RandomTexture);
             effect.Parameters["InvProj"].SetValue(Matrix.Transpose( Matrix.Invert(world.ActiveCamera.Projection)));
             effect.Parameters["View"].SetValue(world.ActiveCamera.View);
             effect.Parameters["jitter"].SetValue(jitter);
             effect.Parameters["halfPixel"].SetValue(EngineStuff.HalfPixel);
             effect.Parameters["diffScale"].SetValue(diffscale);
             effect.Parameters["whiteCorrection"].SetValue(whiteCorrection);

             if (outputONLYSSAOMAP)
             {                 
                 rHelper.RenderTextureToFullScreenVertexPixel(effect);
                 return;
             }

             rHelper.SetUpRenderTarget(target);
             rHelper.RenderTextureToFullScreenVertexPixel(effect);
             Texture2D r = rHelper.GetResultsRenderTarget();

             if (blurMode == BlurMode.SINGLE || blurMode == BlurMode.DOUBLE)
             {
                 rHelper.SetUpRenderTarget(target2);
                 gbp.Draw(r, rHelper, gt, screenRec, world);
                 Texture2D x = rHelper.GetResultsRenderTarget();                

                 if (blurMode == BlurMode.DOUBLE)
                 {
                     rHelper.SetUpRenderTarget(target2);
                     gbp.Draw(x, rHelper, gt, screenRec, world);
                     x = rHelper.GetResultsRenderTarget();                     
                 }
                 ssaofinal.Parameters["SSAOTex"].SetValue(x);
             }
             else if(blurMode == BlurMode.NONE)
             {
                 ssaofinal.Parameters["SSAOTex"].SetValue(r);
             }
             
             ssaofinal.Parameters["SceneTexture"].SetValue(rHelper[PrincipalConstants.CurrentImage]);
             ssaofinal.Parameters["halfPixel"].SetValue(EngineStuff.HalfPixel);
             ssaofinal.Parameters["weight"].SetValue(1);
             rHelper.RenderTextureToFullScreenVertexPixel(ssaofinal);

             //effect.Parameters["g_fSampleRad"].SetValue(15);
             //effect.Parameters["g_fJitter"].SetValue(1);
             //effect.Parameters["g_fIntensity"].SetValue(2);
             //effect.Parameters["g_fScale"].SetValue(200);
             //effect.Parameters["g_fFarClip"].SetValue(world.Camera.FarPlane);            
             //effect.Parameters["mProjectInverse"].SetValue(Matrix.Invert(world.Camera.Projection));
             //effect.Parameters["mView"].SetValue(world.Camera.View);
             //effect.Parameters["vRenderTargetDimension"].SetValue(new Vector2(EngineStuff.BackBufferWidth,EngineStuff.BackBufferHeight));
              
             //rHelper.RenderTextureToFullScreenVertexPixel(effect);



             //effect.Parameters["DepthBuffer"].SetValue(rHelper[PrincipalConstants.dephRT]);
             //effect.Parameters["NormalBuffer"].SetValue(rHelper[PrincipalConstants.normalRt]);
             //effect.Parameters["RandomTexture"].SetValue(RandomTexture);
             //effect.Parameters["g_fSampleRad"].SetValue(15);
             //effect.Parameters["g_fJitter"].SetValue(1);
             //effect.Parameters["g_fIntensity"].SetValue(2);
             //effect.Parameters["g_fScale"].SetValue(200);
             //effect.Parameters["g_fFarClip"].SetValue(world.Camera.FarPlane);
             //effect.Parameters["mProjectInverse"].SetValue(Matrix.Transpose(Matrix.Invert(world.Camera.Projection)));
             //effect.Parameters["mView"].SetValue(world.Camera.View);
             //effect.Parameters["vRenderTargetDimension"].SetValue(new Vector2(EngineStuff.BackBufferWidth, EngineStuff.BackBufferHeight));
             //effect.Parameters["halfPixel"].SetValue(EngineStuff.HalfPixel);


             //rHelper.RenderTextureToFullScreenVertexPixel(effect);


            
                ////rHelper.SetUpRenderTarget(target);
                //rHelper.RenderTextureToFullScreenVertexPixel(effect);
                ////Texture2D r = rHelper.GetResultsRenderTarget();

                //rHelper.SetUpRenderTarget(target);                
                //gbp.Draw(r, rHelper, render, gt, screenRec, world);
                //r = rHelper.GetResultsRenderTarget();

                //ssaofinal.Parameters["SSAOTex"].SetValue(target.GetTexture());
                //ssaofinal.Parameters["SceneTexture"].SetValue(rHelper[PrincipalConstants.CurrentImage]);
                //ssaofinal.Parameters["halfPixel"].SetValue(EngineStuff.HalfPixel);
                //ssaofinal.Parameters["weight"].SetValue(1);
                //rHelper.RenderTextureToFullScreenVertexPixel(ssaofinal);               

        }

        public void init(EngineStuff engine)
        {
            target = EngineStuff.GetDefaultBuffer(EngineStuff.BackBufferWidth, EngineStuff.BackBufferHeight, SurfaceFormat.Color);
            
            target2 = EngineStuff.GetDefaultBuffer(EngineStuff.BackBufferWidth, EngineStuff.BackBufferHeight, SurfaceFormat.Color);
            
            effect = EngineStuff.InternalContentManager.GetAsset<Effect>("SSAOPOST");
            ssaofinal = EngineStuff.InternalContentManager.GetAsset<Effect>("ssaofinal");

            RandomTexture = EngineStuff.InternalContentManager.GetAsset<Texture2D>("random");
            gbp = new GaussianBlurPostEffect();
            (gbp as IPostEffect).init(engine);
            this.engine = engine;

        //    rd = new Vector3[32];
        //    Random r = new Random();
        //    for (int i = 0; i < 32; i++)
        //    {                    
        //        float x = (float)r.NextDouble() * 2.0f - 1.0f;
        //        float y = (float)r.NextDouble() * 2.0f - 1.0f;
        //        float z = (float)r.NextDouble() * 2.0f - 1.0f;

        //        // get length
        //        float length = (float) Math.Sqrt(x * x + y * y + z * z);

        //        // normalize
        //        x /= length;
        //        y /= length;
        //        z /= length;

        //        rd[i] = new Vector3(x, y, z);
        //    }


        //    t = new Texture2D(EngineStuff.GraphicsDevice, 250, 250);
        //    Color[] cor = new  Color[250 * 250];
        //    for (int i = 0; i < 250*250; i++)
        //    {

        //        float x = (float)r.NextDouble() * 2.0f - 1.0f;
        //        float y = (float)r.NextDouble() * 2.0f - 1.0f;
        //        float z = (float)r.NextDouble() * 2.0f - 1.0f;

        //        // get length
        //        float length = (float)Math.Sqrt(x * x + y * y + z * z);

        //        // normalize
        //        x /= length;
        //        y /= length;
        //        z /= length;

        //           byte rr = (byte)( ((x+1.0)*0.5)*255.0f);
        //           byte g = (byte)( ((y+1.0)*0.5)*255.0f);
        //           byte b = (byte)( ((z+1.0)*0.5)*255.0f);
        //           cor [i] = new Color(rr, g, b);
        //    }

        //    t.SetData<Color>(cor);

            

        }

    }
}


